home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-26 | 64.9 KB | 2,223 lines | [TEXT/PJMM] |
- { ******************************************************** }
- { "wBarMenuProc.p" }
- { }
- { by: }
- { James Matthews }
- { < MacTutor -- Nov 88 > }
- { }
- { with color + hierarchical Menu support }
- { and other nifty additions by: }
- { John A. Love, III }
- { [ Washington Apple Pi Users' Group] }
- { }
- { using Symantec's "THINK Lightspeed Pascal", v 3.02 }
- { }
- { ******************************************************** }
-
-
-
-
- UNIT wBarMenuProc;
-
-
-
- INTERFACE
-
-
- USES
- Quickdraw, wBMInterface, wBMGlobals, wBMMiscSubs, OffScreenSubs, wBMScrollSubs;
-
-
- FUNCTION wInitMenus: wMenuBarListHdl;
-
- FUNCTION wGetNewMBar (wp: WindowPtr; wMenuBarID: INTEGER): wMenuBarHandle;
-
- FUNCTION wGetMenuBar (wp: WindowPtr): wMenuBarHandle;
-
- PROCEDURE wSetMenuBar (theMenuBar: wMenuBarHandle; wp: WindowPtr);
-
- PROCEDURE wAddWMB (theMenuBar: wMenuBarHandle);
-
- PROCEDURE wDeleteWMB (wp: WindowPtr);
-
- PROCEDURE wClearMenuBarList (theMenuBarList: wMenuBarListHdl);
-
- PROCEDURE wInsertMenu (theMenuBar: wMenuBarHandle; theMenu: MenuHandle; beforeID: INTEGER);
-
- PROCEDURE wDeleteMenu (theMenuBar: wMenuBarHandle; menuID: INTEGER);
-
- PROCEDURE GetWBMrects (wp: WindowPtr; VAR WBMrect, leftMSArect, rightMSArect: Rect);
-
- { PROCEDURE wSetColorMenu (menusID, itemsID: INTEGER); -- local only }
-
- PROCEDURE wDrawMenuBar (theMenuBar: wMenuBarHandle);
-
- PROCEDURE wScrollMenuBar (theMenuBar: wMenuBarHandle);
-
- PROCEDURE wGetMSA (theMenuBar: wMenuBarHandle);
-
- PROCEDURE wDrawMSA (theMenuBar: wMenuBarHandle);
-
- PROCEDURE wClearMenuBar (theMenuBar: wMenuBarHandle);
-
- FUNCTION wMenuSelect (theMenuBar: wMenuBarHandle; startPt: Point): LONGINT;
-
- FUNCTION wMenuKey (theMenuBar: wMenuBarHandle; ch: char): LONGINT;
-
- PROCEDURE wHiliteMenu (theMenuBar: wMenuBarHandle; menuID: INTEGER);
-
- PROCEDURE wChangeMenuBarSize (wp: WindowPtr; zooming: BOOLEAN);
-
-
-
- IMPLEMENTATION
-
-
-
- PROCEDURE MenuDefProc (message: INTEGER; theMenu: MenuHandle; VAR menuRect: Rect; hitPt: Point; VAR whichItem: INTEGER; theProc: ProcPtr);
-
- INLINE
- $205F, $4E90; { move.l (sp)+,a0 ; jsr (a0) }
-
-
- PROCEDURE MenuDefGlue (message: INTEGER; theMenu: MenuHandle; VAR menuRect: Rect; hitPt: Point; VAR whichItem: INTEGER);
-
- VAR
- mProcState: SignedByte;
-
-
- BEGIN
- LoadResource(theMenu^^.menuProc);
- mProcState := HGetState(theMenu^^.menuProc);
- MoveHHi(theMenu^^.menuProc);
- HLock(theMenu^^.menuProc);
- MenuDefProc(message, theMenu, menuRect, hitPt, whichItem, theMenu^^.menuProc^);
- LoadResource(theMenu^^.menuProc);
- HSetState(theMenu^^.menuProc, mprocState);
- END; { MenuDefGlue }
-
-
- FUNCTION wInitMenus: wMenuBarListHdl;
- { Call immediately after "InitManagers": }
- { }
- { Creates a wMenuBarList and quantifies assorted & sordid global parms. }
-
- VAR
- wMBL: wMenuBarListHdl;
-
-
- BEGIN
-
- wMBL := wMenuBarListHdl(NewClearHandle(SizeOf(wMenuBarList)));
- ;
- IF MemError <> noErr THEN
- BEGIN
- wInitMenus := NIL;
- EXIT(wInitMenus);
- END; { Whoops !! }
-
- { wClearMenuBarList(wMBL); -- NOT needed here !! }
- wInitMenus := wMBL;
-
- { ++ stuff for BIGees: }
-
- IF sizeFont > normalSize THEN { From InitBigScreen PROC call on start-up. }
- BEGIN
- betweenTitles := 18;
- aboveBelowItem := 2;
- menuFrame := 2 * frame;
- menuShadow := 2 * shadow;
- END
- ELSE { small potatoes }
- BEGIN
- betweenTitles := 14;
- aboveBelowItem := 2;
- menuFrame := frame;
- menuShadow := shadow;
- END; { ELSE }
-
- frameShad := menuFrame + menuShadow;
- scrollPolyDXY := mBarHt DIV 2;
- { Neighboring MENUs share inverted space: }
- invertOverlap := (betweenTitles DIV 2) + 1;
-
- END; { wInitMenus }
-
-
- FUNCTION wGetNewMBar (wp: WindowPtr; wMenuBarID: INTEGER): wMenuBarHandle;
- { Pass wMenuBarID = noMBARrsrc if you wish to start fresh }
- { and call wInsertMenu yourself. }
-
- CONST
- none = 0;
-
- TYPE
- rMenuBar = RECORD
- numMenus: INTEGER;
- menuIDs: ARRAY[0..0] OF INTEGER;
- END;
- rMenuBarPtr = ^rMenuBar;
- rMenuBarHdl = ^rMenuBarPtr;
-
- VAR
- rMBar: rMenuBarHdl;
- mh: MenuHandle;
- i: INTEGER;
- theWorld: SysEnvRec;
- itDoesMatter: OSErr;
-
-
- BEGIN
-
- wGetNewMBar := NIL; { Assume the pits !! }
- ;
- IF wp = NIL THEN
- EXIT(wGetNewMBar);
-
- rMBar := rMenuBarHdl(GetResource('MBAR', wMenuBarID));
-
- { Out with the old Window Menu Bar IF there's one & in with the new: }
- wDeleteWMB(wp);
- ;
- mBar := wMenuBarHandle(NewClearHandle(SizeOf(wMenuBar)));
- IF MemError <> noErr THEN
- BEGIN
- IF rMBar <> NIL THEN
- ReleaseResource(Handle(rMBar));
- EXIT(wGetNewMBar);
- END; { Whoops !! }
- mBar^^.titleHilited := noneHilited;
- wSetMenuBar(mBar, wp);
-
- IF (rMBar <> NIL) & (rMBar^^.numMenus > 0) THEN { & so sue me -- I'm paranoid !! }
- BEGIN
- { Save & restore main Menu Color Table so that GetMenu does NOT change it. }
- IF aMac2 THEN
- oldMCTable := GetMCInfo;
-
- FOR i := 0 TO (rMBar^^.numMenus - 1) DO
- BEGIN
- mh := GetMenu(rMBar^^.menuIDs[i]);
- IF mh <> NIL THEN { Paranoid-ville again !! }
- BEGIN
- IF i = 0 THEN { = Apple Menu }
- BEGIN
- { Glue fills in all fields EXCEPT systemVersion: }
- itDoesMatter := SysEnvirons(SysEnvironsVersion, theWorld);
- IF (itDoesMatter = noErr) & (theWorld.systemVersion < $0700) THEN
- BEGIN
- { Attached resource file has a 'sicn' here: }
- SetItemIcon(mh, AboutItem, none);
- SetItemCmd(mh, AboutItem, char(none));
- END;
- AddResMenu(mh, 'DRVR'); { + DAs }
- END; { Apple Menu }
- wInsertMenu(mBar, mh, atEnd);
- DetachResource(Handle(mh)); { For calling GetMenu & AddResMenu lots. }
- END; { IF mh <> NIL }
- END; { FOR }
- ;
- ReleaseResource(Handle(rMBar));
-
- IF aMac2 THEN
- BEGIN
- newMCTable := GetMCInfo; { Safe on the Stack !! }
- SetMCInfo(oldMCTable);
- mbar^^.wMCTable := newMCTable; { Save for drawing & selecting. }
- END; { IF aMac2}
- END; { IF a rMBar }
-
- wGetNewMBar := mBar;
-
- END; { wGetNewMBar }
-
-
- FUNCTION wGetMenuBar (wp: WindowPtr): wMenuBarHandle;
-
- VAR
- i: INTEGER;
-
-
- BEGIN
-
- found := false;
- i := 0;
- ;
- wGetMenuBar := NIL;
- IF mBarList = NIL THEN
- EXIT(wGetMenuBar);
-
- WITH mBarList^^ DO
- BEGIN
- IF numWindows > 0 THEN
- WHILE (NOT found) & (i < numWindows) DO
- IF WMBars[i]^^.wp = wp THEN
- found := true
- ELSE
- i := i + 1 { End of WHILE }
-
- ELSE { zip windows }
- ;
-
- IF found THEN
- wGetMenuBar := WMBars[i];
- END; { WITH }
-
- END; { wGetMenuBar }
-
-
- PROCEDURE wSetMenuBar (theMenuBar: wMenuBarHandle; wp: WindowPtr);
-
-
- BEGIN
- theMenuBar^^.wp := wp; { Simple, aint it ?!!? }
- END; { wSetMenuBar }
-
-
- PROCEDURE wAddWMB (theMenuBar: wMenuBarHandle);
- { For example: }
- { }
- { windPtr := GetNewWindow(); }
- { menuBar := wGetNewMBar(windPtr, barID); }
- { IF menuBar <> NIL THEN }
- { wAddWMB(menuBar); }
-
- VAR
- i: INTEGER;
-
-
- BEGIN
-
- newBarListSize := SizeOf(wMenuBarList) + (mBarList^^.numWindows + 1) * 4;
- IF newBarListSize > GetHandleSize(Handle(mBarList)) THEN
- IF MemError = noErr THEN
- SetHandleSize(Handle(mBarList), newBarListSize);
-
- IF MemError = noErr THEN
- WITH mBarList^^ DO
- BEGIN
- WMBars[numWindows] := theMenuBar;
- numWindows := numWindows + 1
- END; { WITH }
-
- END; { wAddWMB }
-
-
- PROCEDURE wDeleteWMB (wp: WindowPtr);
-
- VAR
- i, j: INTEGER;
-
-
- BEGIN
-
- found := false;
- i := 0;
-
- IF mBarList^^.numWindows > 0 THEN
- BEGIN
-
- WHILE (NOT found) & (i < mBarList^^.numWindows) DO
- IF mBarList^^.WMBars[i]^^.wp = wp THEN
- found := true
- ELSE
- i := i + 1; { End of WHILE }
-
- IF found THEN
- BEGIN
- wClearMenuBar(mBarList^^.WMBars[i]);
- DisposHandle(Handle(mBarList^^.WMBars[i]));
- IF i <> (mBarList^^.numWindows - 1) THEN { Not the last one in the List. }
- FOR j := (i + 1) TO (mBarList^^.numWindows - 1) DO
- mBarList^^.WMBars[j - 1] := mBarList^^.WMBars[j]
- ELSE { Delete the last one. Already done, so nada required here. }
- ;
- mBarList^^.numWindows := mBarList^^.numWindows - 1;
- newBarListSize := GetHandleSize(Handle(mBarList)) - 4;
- IF MemError = noErr THEN
- SetHandleSize(Handle(mBarList), newBarListSize);
- END; { IF found }
-
- END { IF numWindows >0 }
-
- ELSE { zip windows }
- ;
-
- END; { wDeleteWMB }
-
-
- PROCEDURE wClearMenuBarList (theMenuBarList: wMenuBarListHdl);
- { For now, I do NOT use the passed parm because it's a global. }
- { This may change in the future, however. }
-
- CONST
- WindowListLoc = $9D6; { 1st window in linked list. }
-
- VAR
- window: WindowPeek;
-
-
- BEGIN
-
- window := WindowPeek(longPtr(WindowListLoc));
- WHILE window <> NIL DO
- BEGIN
- wDeleteWMB(WindowPtr(window));
- window := window^.nextWindow;
- END; { WHILE }
-
- { The following has already happened after execution of above WHILE loop: }
- { }
- { theMenuBarList^^.numWindows := 0; }
- { SetHandleSize(Handle(theMenuBarList), SizeOf(wMenuBarList)); }
-
- END; { wClearMenuBarList }
-
-
- FUNCTION IncreaseSize (theMenuBar: wMenuBarHandle): OSErr;
-
- VAR
- hState: SignedByte;
-
-
- BEGIN
- newWMBSize := SizeOf(wMenuBar) + (theMenuBar^^.numMenus + 1) * SizeOf(wMenuRec);
- IF newWMBSize > GetHandleSize(Handle(theMenuBar)) THEN
- IF MemError = noErr THEN
- BEGIN
- hState := HGetState(Handle(theMenuBar));
- HUnlock(Handle(theMenuBar));
- SetHandleSize(Handle(theMenuBar), newWMBSize);
- { Just in case entry state is locked: }
- MoveHHi(Handle(theMenuBar));
- HSetState(Handle(theMenuBar), hState);
- END;
- ;
- IncreaseSize := MemError;
- END; { IncreaseSize }
-
-
- FUNCTION DecreaseSize (theMenuBar: wMenuBarHandle): OSErr;
-
- VAR
- hState: SignedByte;
-
-
- BEGIN
- newWMBSize := SizeOf(wMenuBar) + (theMenuBar^^.numMenus - 1) * SizeOf(wMenuRec);
- IF newWMBSize < GetHandleSize(Handle(theMenuBar)) THEN
- IF MemError = noErr THEN
- BEGIN
- hState := HGetState(Handle(theMenuBar));
- HUnlock(Handle(theMenuBar));
- SetHandleSize(Handle(theMenuBar), newWMBSize);
- MoveHHi(Handle(theMenuBar));
- HSetState(Handle(theMenuBar), hState);
- END;
- ;
- DecreaseSize := MemError;
- END; { DecreaseSize }
-
-
- FUNCTION GetTitleWidth (theMenu: MenuHandle): INTEGER;
-
- VAR
- oldTxSize, oldTxFont, oldTxMode: INTEGER;
- oldTxStyle: Style;
-
-
- BEGIN
- oldTxFont := thePort^.txFont;
- oldTxSize := thePort^.txSize;
- oldTxStyle := thePort^.txFace;
- TextFont(systemFont);
- myTextSize(sizeFont);
- TextFace([]);
- ;
- GetTitleWidth := StringWidth(theMenu^^.menuData);
- ;
- TextFont(oldTxFont);
- myTextSize(oldTxSize);
- TextFace(oldTxStyle);
- END; { GetTitleWidth }
-
-
- FUNCTION GetItemIconSize (theMenu: MenuHandle; item: INTEGER): INTEGER;
-
- CONST
- reducedIconCmd = $1D;
- smallIconCmd = $1E;
-
- VAR
- iconNbr: Byte;
- sizeIcon: INTEGER;
- theCICN: CIconHandle;
- cmdChar: char;
-
-
- BEGIN
-
- GetItemIcon(theMenu, item, iconNbr);
- IF iconNbr = 0 THEN
- sizeIcon := 0
- ELSE
- BEGIN
- IF aMac2 THEN
- BEGIN
- theCICN := GetCIcon(iconNbr + 256);
- IF theCICN <> NIL THEN
- BEGIN
- WITH theCICN^^.iconPMap.bounds DO
- sizeIcon := bottom - top;
- DisposCIcon(theCICN);
- END
- ELSE { no cicn }
- sizeIcon := 32;
- END { aMac2 }
- ELSE
- sizeIcon := 32;
-
- GetItemCmd(theMenu, item, cmdChar);
- IF (cmdChar = chr(reducedIconCmd)) | (cmdChar = chr(smallIconCmd)) THEN
- sizeIcon := sizeIcon DIV 2;
- END; { Has either an ICON, a CICN, a reduced icon or a SICN }
-
- GetItemIconSize := sizeIcon;
-
- END; { GetItemIconSize }
-
-
- PROCEDURE wInsertMenu (theMenuBar: wMenuBarHandle; theMenu: MenuHandle; beforeID: INTEGER);
- { Insert a Menu into a defined wMenuBar: }
-
- VAR
- hierID, index, i, j: INTEGER;
- found, enabled: BOOLEAN;
- parentMenuHdl: MenuHandle;
- oldPort: GrafPtr;
- cmdChar, parentMark: char;
- parentItemRect, parentFrameRect: Rect;
- currentHeight, prevHeight, sizeIcon: INTEGER;
-
-
- BEGIN
-
- IF beforeID = atEnd THEN
- BEGIN
-
- i := 0;
- WHILE (i < theMenuBar^^.numMenus) & (theMenuBar^^.wMenus[i].menuType = regMenu) DO
- i := i + 1;
-
- IF i < theMenuBar^^.numMenus THEN
- { Insert after end of regular portion of Window Menu Bar, }
- { which occurs just prior to the Hierarchical portion. }
- BEGIN
- wInsertMenu(theMenuBar, theMenu, theMenuBar^^.wMenus[i].mh^^.menuID);
- EXIT(wInsertMenu);
- END
- ELSE
- BEGIN
- IF IncreaseSize(theMenuBar) <> noErr THEN
- EXIT(wInsertMenu);
- titleWidth := GetTitleWidth(theMenu);
- END; { ELSE: i = numMenus }
-
- END { beforeID = atEnd }
-
- ELSE IF beforeID = hierMenu THEN
- BEGIN
-
- hierID := theMenu^^.menuID;
- i := 0;
- found := false;
- ;
- WHILE (i < theMenuBar^^.numMenus) & NOT found DO { Scan entire wMenuBar. }
- BEGIN
- parentMenuHdl := theMenuBar^^.wMenus[i].mh;
- FOR j := 1 TO CountMItems(parentMenuHdl) DO { Scan each menu. }
- BEGIN
- GetItemCmd(parentMenuHdl, j, cmdChar);
- IF cmdChar = char(hMenuCmd) THEN
- BEGIN
- GetItemMark(parentMenuHdl, j, parentMark);
- IF ord(parentMark) = hierID THEN
- BEGIN
- found := true;
- Leave; { FOR loop }
- END; { IF ord() }
- END; { Hierarchical Menu }
- END; { FOR }
-
- i := i + 1; { IF found, i = correct # plus 1. }
- END; { WHILE }
-
- IF found THEN { ... is it enabled ??? }
- IF j < 32 THEN
- enabled := BitTst(@theMenuBar^^.wMenus[i - 1].mh^^.enableFlags, menuTitleBit - j)
- ELSE
- enabled := true; { Items 32 & beyond. }
-
- IF found & enabled & (IncreaseSize(theMenuBar) = noErr) THEN
- BEGIN
- WITH theMenuBar^^, wMenus[numMenus] DO
- BEGIN
-
- mh := theMenu; { Place at end = Hierarchical portion. }
- menuType := hierMenu;
- parentID := parentMenuHdl^^.menuID;
- { These fields are filled-in later by wMenuSelect }
- { for both Hierarchical and Regular menus: }
- { }
- { menuParentRgn, cumParentRgn and MenuDownOSHdl }
- { }
- { You'll notice that I ignore these fields when }
- { inserting and deleting a Regular menu because }
- { Hierarchical menus are inserted AFTER all Regular }
- { menus and are deleted immediately after use. }
-
- END; { WITH theMenuBar^^, wMenus[numMenus] }
-
- { titleRect = parent item's rect. }
- { }
- { For starters, setup left & right coordinates: }
-
- WITH parentItemRect DO
- BEGIN
- WITH theMenuBar^^.wMenus[i - 1] DO { [i-1] belongs to parentMenuHdl. }
- IF menuType = regMenu THEN
- left := titleRect.left + menuFrame
- ELSE
- left := titleRect.right - 4 * menuFrame + menuFrame;
- CalcMenuSize(parentMenuHdl);
- right := left + parentMenuHdl^^.menuWidth;
- END; { WITH parentItemRect }
-
- WITH theMenuBar^^.wMenus[i - 1] DO
- IF menuType = regMenu THEN
- currentHeight := titleRect.bottom + menuFrame
- ELSE
- currentHeight := titleRect.top + menuFrame;
-
- FOR index := 1 TO j DO
- BEGIN
- prevHeight := currentHeight;
- sizeIcon := GetItemIconSize(parentMenuHdl, index);
- currentHeight := currentHeight + aboveBelowItem + Max(sizeFont, sizeIcon) + aboveBelowItem;
- END; { FOR }
-
- WITH parentItemRect DO { Complete the other two dimensions. }
- BEGIN
- top := prevHeight;
- bottom := currentHeight;
- END; { WITH parentItemRect }
-
- WITH theMenuBar^^, wMenus[i - 1] DO
- BEGIN
- parentFrameRect := parentItemRect; { Change ONLY right & left coords ... }
- WITH parentFrameRect DO
- BEGIN
- left := left - menuFrame;
- right := right + menuFrame + menuShadow;
- END; { WITH parentFrameRect }
-
- GetPort(oldPort);
- { ----- }
- SetPort(wp);
- LocalGlobal(parentFrameRect);
- WITH gScreen DO { GrayRgn's rgnBBox - global coords. }
- BEGIN
- IF parentFrameRect.right > right - 2 * menuFrame THEN { Shift left. }
- IF menuType = regMenu THEN
- OffsetRect(parentFrameRect, right - 2 * menuFrame - parentFrameRect.right, 0)
- ELSE
- OffsetRect(parentFrameRect, -(titleRect.right - titleRect.left - 8 * menuFrame + (parentFrameRect.right - parentFrameRect.left)), 0);
- ;
- IF parentFrameRect.left < left + 2 * menuFrame THEN { Shift right. }
- OffsetRect(parentFrameRect, left + 2 * menuFrame - parentFrameRect.left, 0);
- END; { WITH gScreen }
- GlobalLocal(parentFrameRect); { Back to local window coordinates. }
- { ----- }
- SetPort(oldPort);
-
- parentItemRect := parentFrameRect;
- WITH parentItemRect DO
- BEGIN
- left := left + menuFrame;
- right := right - menuFrame - menuShadow;
- END;
- ;
- { [numMenus] belongs to inserted sub-Menu: }
- wMenus[numMenus].titleRect := parentItemRect;
- numMenus := numMenus + 1;
- END; { WITH theMenuBar^^, wMenus[i - 1] }
-
- END; { IF found & enabled & IncreaseSize }
-
- EXIT(wInsertMenu);
-
- END { beforeID = hierMenu }
-
- ELSE { Smack in the middle somewhere !! }
- BEGIN
-
- IF IncreaseSize(theMenuBar) <> noErr THEN
- EXIT(wInsertMenu);
-
- titleWidth := GetTitleWidth(theMenu);
-
- WITH theMenuBar^^ DO
- BEGIN
-
- i := 0;
- WHILE (i < numMenus) & (wMenus[i].mh^^.menuID <> beforeID) DO
- i := i + 1;
- ;
- IF i <> numMenus THEN
- BEGIN
- FOR j := numMenus DOWNTO (i + 1) DO
- BEGIN
- wMenus[j].mh := wMenus[j - 1].mh;
- wMenus[j].menuType := wMenus[j - 1].menuType;
- wMenus[j].parentID := wMenus[j - 1].parentID;
- { Overkill just to copy top & bottom ... }
- wMenus[j].titleRect := wMenus[j - 1].titleRect;
- { ... now, adjust right & left if a regular Menu. }
- IF wMenus[j].menuType = regMenu THEN
- OffsetRect(wMenus[j].titleRect, titleWidth + betweenTitles, 0);
- END; { FOR j := numMenus DOWNTO (i + 1) }
- END; { IF i <> numMenus }
-
- END; { WITH }
-
- END; { in middle }
-
- { Some wierd arithmetic ... }
-
- WITH theMenuBar^^, wMenus[i].titleRect DO
- BEGIN
-
- top := wp^.portRect.top;
- ;
- bottom := top + mBarHt - menuFrame;
- ;
- left := wp^.portRect.left;
- IF i = 0 THEN { Make room for Menu Scroll Activator -- see "wDrawMSA": }
- left := left + 2 * scrollPolyDXY + menuFrame + betweenTitles - invertOverlap
- ELSE
- left := left + wMenus[i - 1].titleRect.right - invertOverlap + betweenTitles - invertOverlap;
- ;
- right := left + invertOverlap + titleWidth + invertOverlap;
-
- IF numMenus = 0 THEN { 1st call to wInsertMenu. }
- barLength := betweenTitles + titleWidth + betweenTitles
- ELSE
- barLength := barLength + titleWidth + betweenTitles;
-
- wMenus[i].mh := theMenu;
- wMenus[i].menuType := regMenu;
- wMenus[i].parentID := mainMenu;
- numMenus := numMenus + 1;
-
- END; { WITH }
-
- END; { wInsertMenu }
-
-
- PROCEDURE wDeleteMenu (theMenuBar: wMenuBarHandle; menuID: INTEGER);
-
- VAR
- i, j: INTEGER;
-
-
- BEGIN
-
- i := 0;
- WITH theMenuBar^^ DO
- WHILE (i < numMenus) & (wMenus[i].mh^^.menuID <> menuID) DO
- i := i + 1; { End of 1st WITH }
- ;
- IF i <> theMenuBar^^.numMenus THEN
- BEGIN
- IF theMenuBar^^.wMenus[i].menuType = regMenu THEN
- titleWidth := GetTitleWidth(theMenuBar^^.wMenus[i].mh);
-
- WITH theMenuBar^^ DO
- BEGIN
-
- IF wMenus[i].menuType = regMenu THEN
- IF numMenus = 1 THEN { Soon to be zero. }
- barLength := 0
- ELSE
- barLength := barLength - titleWidth - betweenTitles;
-
- FOR j := (i + 1) TO (numMenus - 1) DO
- BEGIN
- wMenus[j - 1].mh := wMenus[j].mh;
- wMenus[j - 1].menuType := wMenus[j].menuType;
- wMenus[j - 1].parentID := wMenus[j].parentID;
- wMenus[j - 1].titleRect := wMenus[j].titleRect;
- IF wMenus[j - 1].menuType = regMenu THEN
- OffsetRect(wMenus[j - 1].titleRect, -(titleWidth + betweenTitles), 0);
- END; { FOR j := (i + 1) TO (numMenus - 1) }
-
- END; { 2nd WITH }
-
- IF DecreaseSize(theMenuBar) = noErr THEN
- ;
- theMenuBar^^.numMenus := theMenuBar^^.numMenus - 1;
- END; { IF i <> theMenuBar^^.numMenus }
-
- END; { wDeleteMenu }
-
-
- PROCEDURE GetWBMrects (wp: WindowPtr; VAR WBMrect, leftMSArect, rightMSArect: Rect);
-
- PROCEDURE ZeroRect (VAR r: Rect);
-
- BEGIN
-
- WITH r DO
- BEGIN
- top := 0;
- left := 0;
- bottom := 0;
- right := 0;
- END; { WITH }
-
- END; { ZeroRect }
-
-
- BEGIN { GetWBMrects }
-
- IF wGetMenuBar(wp) <> NIL THEN
- BEGIN
-
- windType := GetWindowType(wp); { + quantifies "hasGrowIcon" for update Event. }
- WBMrect := wp^.portRect;
- WITH WBMrect DO
- BEGIN
- IF hasGrowIcon THEN
- right := right - (scrollWidth - frame);
- bottom := top + mBarHt;
- END;
-
- leftMSArect := WBMrect;
- WITH leftMSArect DO
- right := left + 2 * scrollPolyDXY + menuFrame;
-
- rightMSArect := WBMrect;
- WITH rightMSArect DO
- left := right - 2 * scrollPolyDXY - menuFrame;
-
- END { window has a Window Bar Menu }
- ELSE
- BEGIN
- ZeroRect(WBMrect);
- ZeroRect(leftMSArect);
- ZeroRect(rightMSArect);
- END; { ELSE }
-
- dynamicBalloons[0].dynamicStrID := 128;
- IF windType = rDocProc THEN
- dynamicBalloons[0].dynamicStrIndex := 3
- ELSE
- dynamicBalloons[0].dynamicStrIndex := 6;
- dynamicBalloons[0].dynamicR := leftMSArect;
- ;
- dynamicBalloons[1].dynamicStrID := 128;
- IF windType = rDocProc THEN
- dynamicBalloons[1].dynamicStrIndex := 2
- ELSE
- dynamicBalloons[1].dynamicStrIndex := 5;
- dynamicBalloons[1].dynamicR := WBMrect;
- InsetRect(dynamicBalloons[1].dynamicR, leftMSArect.right, 0); { Between MSAs. }
- ;
- dynamicBalloons[2].dynamicStrID := 128;
- IF windType = rDocProc THEN
- dynamicBalloons[2].dynamicStrIndex := 4
- ELSE
- dynamicBalloons[2].dynamicStrIndex := 7;
- dynamicBalloons[2].dynamicR := rightMSArect;
-
- END; { GetWBMrects }
-
-
- PROCEDURE GetColors;
-
- BEGIN
-
- IF aMac2 THEN
- BEGIN
- GetBackColor(oldBackColor);
- GetForeColor(oldForeColor);
- END; { IF }
-
- END; { GetColors }
-
-
- PROCEDURE RestoreColors;
-
- BEGIN
-
- IF aMac2 THEN
- BEGIN
- RGBBackColor(oldBackColor);
- RGBForeColor(oldForeColor);
- END; { IF }
-
- END; { RestoreColors }
-
-
- PROCEDURE wSetColorMenu (menusID, itemsID: INTEGER);
- { Without redefining Apple's built-in MenuDefProc, we're restricting }
- { ourselves to ALL Item text (including the mark & CMD-key) being }
- { the same color and ditto for the background color of ALL Items. }
-
- VAR
- MCTBEntry: MCEntryPtr;
- { What we actually got back from GetMCTBEntry }
- { compared with what we asked for, the latter }
- { being the original parms passed to wSetColorMenu: }
- returnedMenuID, returnedMenuItem: INTEGER;
-
-
- FUNCTION GetMCTBEntry (VAR menuID, itemID: INTEGER): MCEntryPtr;
-
- VAR
- mctbEntryPtr: MCEntryPtr;
-
-
- BEGIN
-
- GetMCTBEntry := NIL; { NOT very optimistic, are we ?!!? }
-
- mctbEntryPtr := GetMCEntry(menuID, itemID);
-
- IF mctbEntryPtr = NIL THEN
- { Could NOT find what we asked for, so recurse UP the chain: }
- { }
- { if no specified Item entry, then look for Title entry }
- { if no asked-for Title entry, then look for MenuBar entry }
- { if no specified MenuBar entry, then our 'mctb' resource is NOT correct }
- BEGIN
-
- IF (menuID <> mceMenuBar) & (itemID <> mceMenuTitle) THEN
- BEGIN { Asked for item }
- itemID := mceMenuTitle;
- GetMCTBEntry := GetMCTBEntry(menuID, itemID);
- END
- ELSE IF (menuID <> mceMenuBar) & (itemID = mceMenuTitle) THEN
- BEGIN { Asked for title }
- menuID := mceMenuBar;
- itemID := mceMenuBar;
- GetMCTBEntry := GetMCTBEntry(menuID, itemID);
- END
- ELSE IF (menuID = mceMenuBar) & (itemID = mceMenuBar) THEN
- ; { Ran out of steam !!! }
-
- END
- ELSE
- GetMCTBEntry := mctbEntryPtr;
-
- END; { GetMCTBEntry }
-
-
- BEGIN { wSetColorMenu }
-
- IF NOT aMac2 THEN
- EXIT(wSetColorMenu);
-
- returnedMenuID := menusID; { VARed ... what we actually get }
- returnedMenuItem := itemsID; { back from GetMCTBEntry. }
- ;
- MCTBEntry := GetMCTBEntry(returnedMenuID, returnedMenuItem);
- IF MCTBEntry = NIL THEN
- EXIT(wSetColorMenu);
-
- WITH MCTBEntry^ DO
-
- IF (returnedMenuID <> mceMenuBar) & (returnedMenuItem <> mceMenuTitle) THEN
- BEGIN { Asked for AND got a Menu Item. }
- RGBBackColor(mctRGB4);
- RGBForeColor(mctRGB2);
- END { an Item element}
-
- ELSE IF (returnedMenuID <> mceMenuBar) & (returnedMenuItem = mceMenuTitle) THEN
- BEGIN
- RGBBackColor(mctRGB4);
- IF itemsID = mceMenuTitle THEN { Asked for AND got a Menu Title. }
- RGBForeColor(mctRGB1)
- ELSE { Asked for an Item, recursed to a Title. }
- RGBForeColor(mctRGB3);
- END { a Title element }
-
- ELSE IF (returnedMenuID = mceMenuBar) & (returnedMenuItem = mceMenuBar) THEN
- BEGIN
- { Here, if you ask for the MenuBar entry, I assume you're just interested }
- { in the background color because you're coloring the overall MenuBar via }
- { _EraseRect. If you're really interested in the background color of the }
- { pulled-down Menu, then ask for a Menu Title or a Menu Item entry. }
- IF menusID = mceMenuBar THEN { Got what we asked for !! }
- RGBBackColor(mctRGB4)
- ELSE IF itemsID = mceMenuTitle THEN { Asked for a Title, recursed to MenuBar. }
- BEGIN
- RGBBackColor(mctRGB2);
- RGBForeColor(mctRGB1);
- END
- ELSE { Asked for an Item, recursed TWICE to MenuBar. }
- BEGIN
- RGBBackColor(mctRGB2);
- RGBForeColor(mctRGB3);
- END
- END; { got back a MenuBar element}
- { End of WITH }
-
- END; { wSetColorMenu }
-
-
- PROCEDURE wDrawMenuBar (theMenuBar: wMenuBarHandle);
- { Draw a wMenuBar with appropriate highlighting: }
-
- LABEL
- 100, 200;
-
- VAR
- active: BOOLEAN;
- y0, i: INTEGER;
- lsWBMrect, offBarRect, titleR, visDrawingRect: Rect;
- titleRgn: RgnHandle;
- { Keep safe on Stack to avoid Memory Manager blues ... }
- safeTitle: Str255;
-
-
- BEGIN
-
- IF theMenuBar^^.numMenus = 0 THEN { Nada !! }
- EXIT(wDrawMenuBar);
-
- mbHState := HGetState(Handle(theMenuBar));
- MoveHHi(Handle(theMenuBar));
- HLock(Handle(theMenuBar)); { ... because some TRAPs called inside }
- { the WITH block move memory. }
- GetPort(oldPort);
- SetPort(theMenuBar^^.wp);
- oldClip := NewRgn;
- GetClip(oldClip);
- ;
- GetColors;
- IF aMac2 THEN
- BEGIN
- oldMCTable := GetMCInfo;
- SetMCInfo(theMenuBar^^.wMCTable);
- END; { IF aMac2 }
-
- lsWBMrect := WBMrect; { GetWBMrects already called by wDrawMSA. }
- LocalGlobal(lsWBMrect);
-
- { Local window coordinates are input to & local screen }
- { coordinates are returned from CreateOffScreen: }
-
- WITH theMenuBar^^ DO
- BEGIN
-
- active := (ORD(WindowPeek(wp)^.hilited) <> 0);
-
- { offBarRect may end up being wider than window's portRect. }
- WITH offBarRect DO
- BEGIN
- top := WBMrect.top;
- bottom := WBMrect.bottom - menuFrame;
- left := leftMSArect.right;
- right := left + barLength;
- IF right < rightMSArect.left THEN
- right := rightMSArect.left;
- END; { WITH offBarRect }
-
- IF barOSHdl <> NIL THEN
- BEGIN
- LocalGlobal(offBarRect);
- WITH lScreen DO { _GlobalToLocal }
- OffsetRect(offBarRect, left, top);
- GOTO 100;
- END; { Still there }
-
- barOSHdl := CreateOffScreen(offBarRect);
- IF (QuickStrip(Ptr(barOSHdl)) = NIL) | (barOSHdl^^.CreateOffScreenError <> noErr) THEN
- GOTO 200;
-
- { ELSE draw into off-screen Port as follows: }
-
- TextFont(systemFont);
- myTextSize(sizeFont);
- TextFace([]);
- TextMode(srcOr);
-
- { We canNOT call _GlobalToLocal here because we've changed the portBits.bounds }
- { rectangle of our off-screen port within "CreateOffScreen". }
-
- WITH lScreen DO { Bounds BEFORE change. }
- OffsetRect(lsWBMrect, left, top);
- ;
- ClipRect(offBarRect);
- wSetColorMenu(mceMenuBar, mceMenuBar);
- EraseRect(offBarRect); { Eliminate all stray matter. }
-
- y0 := (mBarHt - menuFrame - sizeFont) DIV 2;
- ;
- FOR i := 0 TO (numMenus - 1) DO
- BEGIN
-
- IF wMenus[i].menuType = hierMenu THEN
- Cycle;
-
- titleR := wMenus[i].titleRect;
- { Convert to local screen coordinates: }
- OffsetRect(titleR, lsWBMrect.left, lsWBMrect.top);
- { Eliminate the overshoot placed there to invert the title, }
- { because all we wish to do is to draw the title string: }
- InsetRect(titleR, invertOverlap, 0);
- ;
- MoveTo(titleR.left, titleR.bottom - y0);
- wSetColorMenu(wMenus[i].mh^^.menuID, mceMenuTitle);
- safeTitle := wMenus[i].mh^^.menuData;
- DrawString(safeTitle);
-
- { Gray-out disabled Menu titles ONLY if window is active. }
- { We dim the whole Window Bar Menu below if window isn't. }
- { The latter allows for CMD-dragging the window. }
-
- IF active & NOT BitTst(@wMenus[i].mh^^.enableFlags, menuTitleBit) THEN
- BEGIN
- titleRgn := NewRgn;
- RectRgn(titleRgn, titleR);
- DimRgn(titleRgn);
- DisposeRgn(titleRgn);
- END; { Gray-out disabled title }
-
- END; { FOR ... drawing off-screen }
- 100:
- ToOnScreen(barOSHdl); { Back to "Square 1". }
-
- WITH barOSHdl^^ DO
- BEGIN
- visDrawingRect := drawingRect;
-
- ClipRect(drawingRect);
-
- BackColor(whiteColor); { So funny colorization }
- ForeColor(blackColor); { does NOT happen !! }
- ;
- WITH visDrawingRect DO { Adjust if overlapping right MSA. }
- IF right > rightMSArect.left THEN
- right := rightMSArect.left;
- onScreenRgn := NewRgn;
- RectRgn(onScreenRgn, visDrawingRect);
- CalcVis(WindowPeek(wp)); { Radius' TOM INIT. }
- SectRgn(onScreenRgn, wp^.visRgn, onScreenRgn);
- CopyBits(offBitMapPtr^, wp^.portBits, offBarRect, drawingRect, srcCopy, onScreenRgn);
-
- { Consider you're CMD-dragging ... }
- IF NOT active THEN
- DimRgn(onScreenRgn);
- ValidRgn(onScreenRgn);
- DisposeRgn(onScreenRgn);
- END; { WITH barOSHdl^^ }
- 200:
- DisposOffScreen(barOSHdl);
-
- END; { WITH theMenuBar^^ }
-
- HSetState(Handle(theMenuBar), mbHState); { Deliberately last !! }
- { ... we're safe now }
- RestoreColors;
- IF aMac2 THEN
- SetMCInfo(oldMCTable);
- ;
- SetClip(oldClip);
- DisposeRgn(oldClip);
- SetPort(oldPort);
-
- wHiliteMenu(theMenuBar, 0); { Appropriate highlighting = none. }
-
- END; { wDrawMenuBar }
-
-
- PROCEDURE wScrollMenuBar (theMenuBar: wMenuBarHandle);
-
- CONST
- toRight = 1;
- toLeft = -1;
-
- VAR
- mouseLoc: Point;
- nbrMenus, direction, temp, deltaScroll, i: INTEGER;
-
-
- BEGIN
-
- nbrMenus := theMenuBar^^.numMenus;
-
- GetMouse(mouseLoc);
- IF PtInRect(mouseLoc, leftMSArect) THEN
- direction := toRight
- ELSE IF PtInRect(mouseLoc, rightMSArect) THEN
- direction := toLeft
- ELSE
- EXIT(wScrollMenuBar); { Should NOT happen !! }
-
- WHILE WaitMouseUp DO
- BEGIN
- IF direction = toRight THEN
- BEGIN
- temp := leftMSArect.right + betweenTitles - invertOverlap - mBar^^.wMenus[0].titleRect.left;
- IF temp <= 0 THEN
- Leave
- ELSE
- deltaScroll := Min(StringWidth('A'), temp);
- END
- ELSE { direction = toLeft }
- BEGIN
- temp := rightMSArect.left - (mBar^^.wMenus[nbrMenus - 1].titleRect.right - invertOverlap + betweenTitles);
- IF temp >= 0 THEN
- Leave
- ELSE
- deltaScroll := Min(StringWidth('A'), -temp); { Absolute value. }
- END;
-
- deltaScroll := direction * deltaScroll;
- FOR i := 0 TO (nbrMenus - 1) DO
- OffsetRect(theMenuBar^^.wMenus[i].titleRect, deltaScroll, 0);
- wDrawMSA(theMenuBar);
- wDrawMenuBar(theMenuBar);
- END; { WHILE }
-
- END; { wScrollMenuBar }
-
-
- PROCEDURE wGetMSA (theMenuBar: wMenuBarHandle);
- { NOTE that lines drawn between _OpenPoly & _ClosePoly have zero-width. }
- { Only when _FramePoly actually draws the polygon <see "wDrawMSA">, do }
- { the pen's attributes such as pen size take effect with the line }
- { thickness being on the INSIDE. }
-
- VAR
- dx, dy, over, back, up, down: INTEGER;
- tempPoly: PolyHandle;
-
-
- BEGIN
-
- WITH WBMrect DO
- BEGIN
- GetPort(oldPort);
- SetPort(theMenuBar^^.wp);
-
- GetWBMrects(theMenuBar^^.wp, WBMrect, leftMSArect, rightMSArect);
-
- { ---------- }
- { Get Menu Scroll Activator(MSA) at left of Window Bar Menu: }
-
- dx := 3 * (scrollPolyDXY DIV 2);
- dy := (bottom - menuFrame - top - scrollPolyDXY) DIV 2;
- over := scrollPolyDXY;
- back := -over;
- up := -scrollPolyDXY;
- down := scrollPolyDXY DIV 2;
-
- IF theMenuBar^^.leftScrollPoly = NIL THEN
- BEGIN
- { theMenuBar^^.leftScrollPoly := OpenPoly; -- I can't believe I did this ?!*!? }
- tempPoly := OpenPoly;
- theMenuBar^^.leftScrollPoly := tempPoly;
- MoveTo(left + dx, bottom - menuFrame - dy);
- Line(0, up); { Vertical part ... }
- Line(back, down); { ... horizontal parts: }
- Line(over, down);
- ClosePoly;
- END; { Doesn't exist, so make a new one }
-
- { ---------- }
- { Get MSA at right of Window Bar Menu: }
-
- IF theMenuBar^^.rightScrollPoly = NIL THEN
- BEGIN
- tempPoly := OpenPoly;
- theMenuBar^^.rightScrollPoly := tempPoly;
- MoveTo(right - dx, bottom - menuFrame - dy);
- Line(0, up); { Vertical part ... }
- Line(over, down); { ... horizontal parts: }
- Line(back, down);
- ClosePoly;
- END; { IF }
-
- SetPort(oldPort);
- END; { WITH WBMrect }
-
- END; { wGetMSA }
-
-
- PROCEDURE wDrawMSA (theMenuBar: wMenuBarHandle);
- { ... AND the bottom line bordering the Window Bar Menu. }
-
- LABEL
- 100;
-
- VAR
- dx, dy: INTEGER;
- aux: BOOLEAN;
- frameColor: RGBColor;
-
-
- BEGIN
-
- WITH WBMrect DO
- BEGIN
- GetPort(oldPort);
- SetPort(theMenuBar^^.wp);
- GetPenState(pnState);
-
- { ---------- }
- { Get the Window Bar Menu rect & draw a line beneath it: }
-
- wGetMSA(theMenuBar); { Calls GetWBMrects. }
- gWBMrect := WBMrect;
- LocalGlobal(gWBMrect);
- IF NOT SectRect(gWBMrect, gScreen, visRect) THEN
- GOTO 100;
- GlobalLocal(visRect);
- onScreenRgn := NewRgn;
- RectRgn(onScreenRgn, visRect);
- SectRgn(onScreenRgn, theMenuBar^^.wp^.visRgn, onScreenRgn);
- oldClip := NewRgn;
- GetClip(oldClip);
- SetClip(onScreenRgn);
- ;
- aux := GetWindowPartColor(theMenuBar^^.wp, wFrameColor, frameColor);
- IF (colorDepth > 1) & aux THEN
- BEGIN
- GetForeColor(oldForeColor);
- RGBForeColor(frameColor);
- END; { Draw in color }
- ;
- PenNormal;
- PenSize(menuFrame, menuFrame);
- MoveTo(left, bottom - menuFrame);
- Line(right - left, 0);
-
- { ---------- }
- { Draw Menu Scroll Activator(MSA) at left of Window Bar Menu: }
-
- IF theMenuBar^^.wMenus[0].titleRect.left < leftMSArect.right + betweenTitles - invertOverlap THEN
- FillPoly(theMenuBar^^.leftScrollPoly, black)
- ELSE
- BEGIN
- FillPoly(theMenuBar^^.leftScrollPoly, white);
- FramePoly(theMenuBar^^.leftScrollPoly);
- END;
-
- { ---------- }
- { Draw vertical line separating MSA from Menu titles: }
-
- MoveTo(left + 2 * scrollPolyDXY, bottom - menuFrame);
- Line(0, -(bottom - top - menuFrame));
-
- { ---------- }
- { Draw MSA at right of Window Bar Menu: }
-
- IF theMenuBar^^.wMenus[theMenuBar^^.numMenus - 1].titleRect.right - invertOverlap + betweenTitles > rightMSArect.left THEN
- FillPoly(theMenuBar^^.rightScrollPoly, black)
- ELSE
- BEGIN
- FillPoly(theMenuBar^^.rightScrollPoly, white);
- FramePoly(theMenuBar^^.rightScrollPoly);
- END;
- ;
- MoveTo(right - 2 * scrollPolyDXY - menuFrame, bottom - menuFrame); { + vertical }
- Line(0, -(bottom - top - menuFrame)); { line. }
-
- IF ORD(WindowPeek(theMenuBar^^.wp)^.hilited) = 0 THEN
- DimRgn(onScreenRgn);
-
- ValidRgn(onScreenRgn);
- DisposeRgn(onScreenRgn);
- SetClip(oldClip);
- DisposeRgn(oldClip);
-
- IF (colorDepth > 1) & aux THEN
- RGBForeColor(oldForeColor);
- 100:
- SetPenState(pnState);
- SetPort(oldPort);
- END; { WITH }
-
- END; { wDrawMSA }
-
-
- PROCEDURE wClearMenuBar (theMenuBar: wMenuBarHandle);
- { Called internally by wDeleteWMB to kiss some Handles goodbye. }
-
-
- BEGIN
-
- mbHState := HGetState(Handle(theMenuBar));
- MoveHHi(Handle(theMenuBar));
- HLock(Handle(theMenuBar));
-
- WITH theMenuBar^^ DO
- BEGIN
- wHiliteMenu(theMenuBar, 0);
-
- IF leftScrollPoly <> NIL THEN { So sue me ... I'm paranoid !! }
- BEGIN
- KillPoly(leftScrollPoly);
- leftScrollPoly := NIL; { Mark as gone ... }
- END;
- ;
- IF rightScrollPoly <> NIL THEN
- BEGIN
- KillPoly(rightScrollPoly);
- rightScrollPoly := NIL;
- END;
-
- IF barOSHdl <> NIL THEN
- DisposOffScreen(barOSHdl); { Sets barOSHdl := NIL }
- END; { WITH }
-
- HSetState(Handle(theMenuBar), mbHState);
-
- END; { wClearMenuBar }
-
-
- FUNCTION wMenuSelect (theMenuBar: wMenuBarHandle; startPt: Point): LONGINT;
- { Pull down the Menus and let the user select an Item: }
- { NOTE -- "startPt" is in Global coordinates, but }
- { ONLY to be compatible with _MenuSelect. }
-
- LABEL
- 100, 200;
-
- CONST
- TopMenuItemLoc = $A0A;
- AtMenuBottomLoc = $A0C;
- MenuFlashAddr = $A24;
- HiliteMode = $938;
-
- VAR
- oldPort: GrafPtr; { Many Locals because of recursion ... }
- oldClip: RgnHandle;
- oldForeColor, oldBackColor: RGBColor;
- screenBounds, betweenMSAs, visAllTitles, visThisTitle, visString: Rect;
- menuRect, menuFrameRect, lsMenuRect, lsWBMrect, lsTitleRect: Rect;
- lStartPt, hierPt, nilPt: Point;
- itemsHeight, i, j, blink: INTEGER;
- saveScrollInfo: LONGINT;
- menuFlashP: wordPtr;
- strayed: BOOLEAN;
- cmdChar, itemMark: char;
- hierMenuHdl: MenuHandle;
- origMCTable, parentMCTable, hierMCTable: MCTableHandle;
- hierSelect: LONGINT;
- onCScreen: CGrafPort;
- onCScreenPtr: CGrafPtr;
- onBWScreen: GrafPort;
- onBWScreenPtr: GrafPtr;
- MenuDownOSHdl: OffScreenRecHdl;
- { Murphy's Memory Manager ... }
- tempRgn1, tempRgn2, tempRgn3: RgnHandle;
-
-
- FUNCTION ItDoesFit (theMenu: MenuHandle; maxMenuHeight: INTEGER; VAR cumMenuHeight: INTEGER): BOOLEAN;
- { Get maximum cum height that can fit within the specified max height. }
-
- VAR
- prevMenuHeight, index, sizeItemIcon: INTEGER;
-
-
- BEGIN
-
- ItDoesFit := true; { Be upbeat !! }
- IF theMenu^^.menuHeight <= maxMenuHeight THEN
- BEGIN
- cumMenuHeight := theMenu^^.menuHeight;
- EXIT(ItDoesFit);
- END;
-
- cumMenuHeight := 0; { For starters ... }
-
- FOR index := 1 TO CountMItems(theMenu) DO
- BEGIN
- prevMenuHeight := cumMenuHeight;
- sizeItemIcon := GetItemIconSize(theMenu, index);
- cumMenuHeight := cumMenuHeight + aboveBelowItem + Max(sizeFont, sizeItemIcon) + aboveBelowItem;
- IF cumMenuHeight > maxMenuHeight THEN
- Leave; { FOR loop }
- END; { FOR }
-
- IF index - 1 < 3 THEN
- ItDoesFit := false
- ELSE IF sizeItemIcon = 0 THEN { ... of first item NOT shown. }
- cumMenuHeight := prevMenuHeight
- ELSE
- { Prevents drawing of the top pixels of any icon in first item NOT shown: }
- cumMenuHeight := prevMenuHeight - aboveBelowItem;
-
- END; { ItDoesFit }
-
-
- FUNCTION GetParentMenuInfo (theMenuBar: wMenuBarHandle; hierMenuNbr: INTEGER): LONGINT;
- { Returns parent menu # in Hi word and parent item # in the low word: }
- { NEVER say it can NEVER fail !!! }
-
- VAR
- hierID, parentMenuNum, j: INTEGER;
- parentMenuHdl: MenuHandle;
- cmdChar, parentMark: char;
- temp: LONGINT;
-
-
- BEGIN
-
- WITH theMenuBar^^ DO
- BEGIN
- parentMenuNum := 0;
- WHILE (parentMenuNum < numMenus) & (wMenus[hierMenuNbr].parentID <> wMenus[parentMenuNum].mh^^.menuID) DO
- parentMenuNum := parentMenuNum + 1;
-
- IF parentMenuNum = numMenus THEN { It better NOT be !!! }
- ;
- hierID := wMenus[hierMenuNbr].mh^^.menuID;
- parentMenuHdl := wMenus[parentMenuNum].mh;
- END; { WITH }
-
- FOR j := 1 TO CountMItems(parentMenuHdl) DO
- BEGIN
- GetItemCmd(parentMenuHdl, j, cmdChar);
- IF cmdChar = char(hMenuCmd) THEN
- BEGIN
- GetItemMark(parentMenuHdl, j, parentMark);
- IF ord(parentMark) = hierID THEN
- Leave; { FOR loop }
- END;
- END; { FOR }
-
- temp := parentMenuNum;
- temp := BitShift(temp, 16) + j;
- GetParentMenuInfo := temp;
-
- END; { GetParentMenuInfo }
-
-
- PROCEDURE RedrawParentItem (theMenuBar: wMenuBarHandle; hierMenuNbr: INTEGER);
- { Apple's MenuDefProc does NOT call _InverRect for a color Mac, }
- { but rather _EraseRect followed by a redraw of the Menu item }
- { with reversed background and hilite colors. As you can see }
- { below, however, I am prone to cheating: }
-
-
- { CONST }
- { TopMenuItemLoc = $A0A; }
- { AtMenuBottomLoc = $A0C; }
-
- VAR
- saveScrollInfo: LONGINT; { MUST be local !!! }
- parentMenuInfo: LONGINT;
- parentMenuNum, redrawitem: INTEGER;
- redrawPt: Point;
- parentMenuHdl: MenuHandle;
- parentMenuRect: Rect;
-
-
- BEGIN
-
- IF NOT aMac2 THEN
- EXIT(RedrawParentItem);
-
- parentMenuInfo := GetParentMenuInfo(theMenuBar, hierMenuNbr);
- parentMenuNum := HiWord(parentMenuInfo);
- redrawItem := LoWord(parentMenuInfo);
-
- WITH theMenuBar^^.wMenus[parentMenuNum] DO
- BEGIN
- parentMenuHdl := mh;
- parentMenuRect := menuParentRgn^^.rgnBBox;
- END;
- ClipRect(parentMenuRect); { For call to "mChooseMsg" below. }
- WITH lScreen DO { LocalToGlobal }
- OffsetRect(parentMenuRect, -left, -top);
-
- SetPt(redrawPt, 0, 0);
- saveScrollInfo := longPtr(TopMenuItemLoc)^;
- wordPtr(TopMenuItemLoc)^ := parentMenuRect.top;
- wordPtr(AtMenuBottomLoc)^ := parentMenuRect.bottom;
- MenuDefGlue(mChooseMsg, parentMenuHdl, parentMenuRect, redrawPt, redrawItem);
- longPtr(TopMenuItemLoc)^ := saveScrollInfo;
-
- END; { RedrawParentItem }
-
-
- BEGIN { wMenuSelect }
-
- { Note that starting here, we sure could use WITH theMenuBar^^ & WITH wMenus[i] }
- { statements for shorthand. However, we'd then need to call HLock. This would }
- { be okay except when we later implement Hierarchical menus via a recursive }
- { to ourself (wMenuSelect). This unnecessarily keeps a locked Handle around for }
- { a long time. [ See "The Secret Life of the Memory Manager" by Richard Clark }
- { in "develop", Volume 1, Issue 2, April 1990 ] In addition, for Hierarchical }
- { menus, we call wInsertMenu and wDeleteMenu which in turn call the IncreaseSize }
- { and DecreaseSize PROCs. These latter PROCs move "theMenuBar" because we need }
- { to temporarily unlock this handle ... therefore ... }
-
- GetPort(oldPort);
- SetPort(theMenuBar^^.wp);
- oldClip := NewRgn;
- GetClip(oldClip);
- ;
- IF aMac2 THEN
- BEGIN
- GetBackColor(oldBackColor); { "GetColors" is local due to recursion. }
- GetForeColor(oldForeColor);
- origMCTable := GetMCInfo;
- SetMCInfo(theMenuBar^^.wMCTable);
- END; { IF aMac2 }
- ;
- menuFlashP := wordPtr(MenuFlashAddr);
-
- WHILE WaitMouseUp DO
- BEGIN
-
- whichItem := 0; { May NOT be in a titleRect. }
-
- i := theMenuBar^^.numMenus - 1; { Find the Menu title that user is selecting. }
- GlobalToLocal(startPt); { Local window coordinates. }
- WHILE (i >= 0) & NOT PtInRect(startPt, theMenuBar^^.wMenus[i].titleRect) DO
- i := i - 1;
-
- IF i >= 0 THEN { Have Menu drop ... }
- BEGIN
-
- lsTitleRect := theMenuBar^^.wMenus[i].titleRect;
- ;
- IF theMenuBar^^.wMenus[i].menuType = regMenu THEN
- BEGIN
-
- { Otherwise strayed = TRUE momentarily as you hit the line bordering }
- { titleRect & menuRect in the process of pulling down a MENU (see below): }
- lsTitleRect.bottom := lsTitleRect.bottom + menuFrame;
-
- { ... AND if the Window Menu Bar is scrolled ... }
- { don't forget about the invertOverlap arithmetic which would enable the }
- { Mouse to be over the expanded titleRect WITHOUT the first/last title }
- { character being visible. The equations below avoid this happenstance. }
- { In addition, "menuFrame" is used to account for a character width > an }
- { image width as well as a character origin > 0. }
-
- screenBounds := gScreen;
- GlobalLocal(screenBounds);
- betweenMSAs := WBMrect;
- InsetRect(betweenMSAs, leftMSArect.right, 0); { ... or rightMSArect.left }
- IF NOT SectRect(screenBounds, betweenMSAs, visAllTitles) THEN
- GOTO 100; { Will NOT happen !! }
-
- IF NOT SectRect(visAllTitles, lsTitleRect, visThisTitle) THEN
- GOTO 100; { Ditto !! }
-
- visString := visThisTitle;
- WITH visString DO
- BEGIN
- IF (leftMSArect.right > right - invertOverlap - 2 * menuFrame) | (screenBounds.left > right - invertOverlap - 2 * menuFrame) THEN
- right := right - invertOverlap - 2 * menuFrame;
- ;
- IF (rightMSArect.left < left + invertOverlap + 2 * menuFrame) | (screenBounds.right < left + invertOverlap + 2 * menuFrame) THEN
- left := left + invertOverlap + 2 * menuFrame;
- END; { WITH visString }
- IF EmptyRect(visString) THEN
- GOTO 100;
-
- END; { a regular Menu }
-
- LocalGlobal(lsTitleRect);
-
- lsWBMrect := WBMrect; { Needed for vertical scrolling ... }
- InsetRect(lsWBMrect, leftMSArect.right, 0); { ... or rightMSArect.left }
- LocalGlobal(lsWBMrect);
-
- LocalToGlobal(startPt);
-
- CalcMenuSize(theMenuBar^^.wMenus[i].mh);
-
- WITH theMenuBar^^.wMenus[i], titleRect DO
- IF menuType = regMenu THEN
- SetRect(menuFrameRect, left, bottom, left + menuFrame + mh^^.menuWidth + frameShad, bottom + menuFrame + mh^^.menuHeight + frameShad)
- ELSE
- SetRect(menuFrameRect, right - 4 * menuFrame, top, right - 4 * menuFrame + menuFrame + mh^^.menuWidth + frameShad, top + menuFrame + mh^^.menuHeight + frameShad);
-
- { If Menu overlaps the screen's edges, trim and/or shift it: }
- LocalGlobal(menuFrameRect);
- WITH gScreen DO
- BEGIN
- IF menuFrameRect.bottom > bottom - 2 * menuFrame THEN
- menuFrameRect.bottom := bottom - 2 * menuFrame;
- ;
- IF menuFrameRect.right > right - 2 * menuFrame THEN { Shift left. }
- IF theMenuBar^^.wMenus[i].menuType = regMenu THEN
- OffsetRect(menuFrameRect, right - 2 * menuFrame - menuFrameRect.right, 0)
- ELSE
- OffsetRect(menuFrameRect, -(theMenuBar^^.wMenus[i].titleRect.right - theMenuBar^^.wMenus[i].titleRect.left - 8 * menuFrame + (menuFrameRect.right - menuFrameRect.left)), 0);
- ;
- IF menuFrameRect.left < left + 2 * menuFrame THEN { Shift right. }
- OffsetRect(menuFrameRect, left + 2 * menuFrame - menuFrameRect.left, 0);
- END; { WITH gScreen }
- GlobalLocal(menuFrameRect); { Back to local window coordinates. }
-
- WITH menuFrameRect DO
- IF ItDoesFit(theMenuBar^^.wMenus[i].mh, bottom - top - menuFrame - frameShad, itemsHeight) THEN
- bottom := top + menuFrame + itemsHeight + frameShad
- ELSE IF theMenuBar^^.wMenus[i].menuType = regMenu THEN
- BEGIN { Damn SysBeep drove me nuts/nuttier !!! }
- wHiliteMenu(theMenuBar, theMenuBar^^.wMenus[i].mh^^.menuID);
- Delay(flashDelay * 2, finalTicks);
- wHiliteMenu(theMenuBar, 0);
- Delay(flashDelay * 2, finalTicks);
- GOTO 100;
- END
- ELSE
- BEGIN
- SetPort(oldPort); { From Open(C)Port on the previous go-around. }
- WITH lScreen DO
- OffsetRect(lsTitleRect, left, top); { GlobalToLocal }
- Delay(flashDelay * 2, finalTicks);
- IF aMac2 THEN
- RedrawParentItem(theMenuBar, i) { i = Hierarchical Menu # }
- ELSE
- BEGIN
- ClipRect(lsTitleRect);
- InvertRect(lsTitleRect);
- END;
- Delay(flashDelay * 2, finalTicks);
- SetPort(theMenuBar^^.wp); { So we can reset its clipRgn on exit. }
- Leave;
- END; { does NOT fit & WITH menuFrameRect }
-
- { MenuDefProc's "mChooseMsg" handles hiliting for a Hierarchical menu item: }
- IF theMenuBar^^.wMenus[i].menuType = regMenu THEN
- wHiliteMenu(theMenuBar, theMenuBar^^.wMenus[i].mh^^.menuID);
-
- MenuDownOSHdl := CreateOffScreen(menuFrameRect);
- IF (QuickStrip(Ptr(MenuDownOSHdl)) = NIL) | (MenuDownOSHdl^^.CreateOffScreenError <> noErr) THEN
- BEGIN
- DisposOffScreen(MenuDownOSHdl);
- GOTO 200;
- END; { Whoops !! }
-
- ClipRect(menuFrameRect); { Draw off-screen ... }
- EraseRect(menuFrameRect); { Eliminate all stray matter. }
-
- { An alternate "ToOnScreen" so our Menu can overlap the window's }
- { boundaries rather than be confined to just its portRect: }
- IF aMac2 THEN
- BEGIN
- SetGDevice(MenuDownOSHdl^^.oldDevice);
- onCScreenPtr := @onCScreen;
- OpenCPort(onCScreenPtr);
- RectRgn(onCScreenPtr^.visRgn, gScreen); { Multiple screens ... }
- onCScreenPtr^.portRect := gScreen;
- END { IF aMac2 }
- ELSE
- BEGIN
- onBWScreenPtr := @onBWScreen;
- OpenPort(onBWScreenPtr);
- RectRgn(onBWScreenPtr^.visRgn, gScreen);
- onBWScreenPtr^.portRect := gScreen;
- END; { ELSE = "Yucky" black-and-white }
-
- ClipRect(menuFrameRect);
- { Save current screen image: }
- BackColor(whiteColor);
- ForeColor(blackColor);
- CopyBits(thePort^.portBits, MenuDownOSHdl^^.offBitMapPtr^, menuFrameRect, menuFrameRect, srcCopy, NIL);
-
- TextFont(systemFont);
- myTextSize(sizeFont);
- TextFace([]);
- TextMode(srcOr);
-
- { NOW, the magic ~~ Mike Shuster, MacTutor <Dec, 85> }
-
- menuRect := menuFrameRect;
- WITH menuRect DO
- BEGIN { Draw frame, then shadow. }
- GetPenState(pnState);
- PenNormal;
-
- right := right - menuShadow;
- bottom := bottom - menuShadow;
- wSetColorMenu(theMenuBar^^.wMenus[i].mh^^.menuID, mceMenuTitle);
- EraseRect(menuRect); { Inside shadow. }
- PenSize(menuFrame, menuFrame);
- FrameRect(menuRect);
- InsetRect(menuRect, menuFrame, menuFrame); { Inside frame AND shadow. }
- ;
- MoveTo(left + menuShadow, bottom + menuFrame);
- PenSize(menuShadow, menuShadow);
- Line((right - left + menuFrame), 0);
- MoveTo(right + menuFrame, bottom + frameShad);
- Line(0, -(bottom - top + menuFrame));
-
- SetPenState(pnState);
- END; { WITH menuRect }
-
- lsMenuRect := menuRect; { Save for later ... }
-
- WITH lScreen DO
- BEGIN
- OffsetRect(menuRect, -left, -top); { LocalToGlobal }
- OffsetRect(lsTitleRect, left, top); { GlobalToLocal ... }
- OffsetRect(lsWBMrect, left, top);
- END; { WITH lScreen }
-
- IF theMenuBar^^.wMenus[i].menuType = regMenu THEN { ... or parentID = mainMenu. }
- BEGIN
- tempRgn1 := NewRgn;
- RectRgn(tempRgn1, lsWBMrect);
- theMenuBar^^.wMenus[i].cumParentRgn := tempRgn1;
- tempRgn2 := NewRgn;
- RectRgn(tempRgn2, lsMenuRect);
- theMenuBar^^.wMenus[i].menuParentRgn := tempRgn2;
- END
- ELSE
- BEGIN
- j := HiWord(GetParentMenuInfo(theMenuBar, i)); { i = Hierarchical Menu # }
- tempRgn1 := NewRgn;
- tempRgn2 := theMenuBar^^.wMenus[j].cumParentRgn;
- tempRgn3 := theMenuBar^^.wMenus[j].menuParentRgn;
- UnionRgn(tempRgn2, tempRgn3, tempRgn1);
- theMenuBar^^.wMenus[i].cumParentRgn := tempRgn1;
- tempRgn2 := NewRgn;
- RectRgn(tempRgn2, lsMenuRect);
- theMenuBar^^.wMenus[i].menuParentRgn := tempRgn2;
- END;
-
- { Start fresh with each scrollable Menu: }
- saveScrollInfo := longPtr(TopMenuItemLoc)^;
- wordPtr(TopMenuItemLoc)^ := menuRect.top;
- wordPtr(AtMenuBottomLoc)^ := menuRect.bottom;
-
- { I encountered a few "cosmetic" problems with Apple's MenuDefProc. }
- { 1) the disabled dotted line will overwrite the right border of the frame. }
- { 2) if there is an icon immediately below the last item that shows in a }
- { scrolling menu, the bottom border of the frame is overwritten by a }
- { portion of said icon. }
- { The call to ClipRect solves both: }
- ClipRect(lsMenuRect);
- { whichItem := 0; -- at beginning of WHILE WaitMouseUp DO }
- MenuDefGlue(mDrawMsg, theMenuBar^^.wMenus[i].mh, menuRect, startPt, whichItem);
-
- strayed := false; { = Mouse on Menu Item OR on Menu title }
- { OR NOT on another Menu. }
- WHILE WaitMouseup & NOT strayed DO { While still selecting in this Menu ... }
- BEGIN
- GetMouse(startPt);
- lStartPt := startPt;
- SubPt(lScreen.topLeft, startPt); { LocalToGlobal }
- MenuDefGlue(mChooseMsg, theMenuBar^^.wMenus[i].mh, menuRect, startPt, whichItem);
-
- IF whichItem <> 0 THEN { Item is enabled. }
- BEGIN
- GetItemCmd(theMenuBar^^.wMenus[i].mh, whichItem, cmdChar);
-
- IF cmdChar = char(hMenuCmd) THEN { a Hierarchical Menu ... }
- BEGIN
- IF aMac2 THEN
- parentMCTable := theMenuBar^^.wMCTable;
- hierPt := startPt;
- GetItemMark(theMenuBar^^.wMenus[i].mh, whichItem, itemMark);
- hierMenuHdl := GetMenu(ord(itemMark));
- wInsertMenu(theMenuBar, hierMenuHdl, hierMenu);
- DetachResource(Handle(hierMenuHdl));
- IF aMac2 THEN
- BEGIN
- hierMCTable := GetMCInfo;
- SetMCInfo(parentMCTable);
- theMenuBar^^.wMCTable := hierMCTable;
- END; { IF aMac2 }
- hierSelect := wMenuSelect(theMenuBar, hierPt);
- wDeleteMenu(theMenuBar, ord(itemMark));
- ;
- whichMenu := HiWord(hierSelect);
- whichItem := LoWord(hierSelect);
-
- IF whichItem <> 0 THEN { So a parent Menu Item does NOT blink: }
- BEGIN
- strayed := true;
- Leave;
- END;
- END
-
- ELSE { a regular Menu }
- whichMenu := theMenuBar^^.wMenus[i].mh^^.menuID;
-
- END; { enabled Item }
-
- strayed := NOT PtInRgn(lStartPt, theMenuBar^^.wMenus[i].menuParentRgn) & NOT PtInRect(lStartPt, lsTitleRect) & PtInRgn(lStartPt, theMenuBar^^.wMenus[i].cumParentRgn);
- END; { WHILE WaitMouseup & NOT strayed }
-
- IF (whichItem <> 0) & NOT strayed THEN
- FOR blink := 1 TO menuFlashP^ DO
- BEGIN
- SetPt(nilPt, 0, 0);
- MenuDefGlue(mChooseMsg, theMenuBar^^.wMenus[i].mh, menuRect, nilPt, whichItem);
- Delay(flashDelay DIV 4, finalTicks);
- MenuDefGlue(mChooseMsg, theMenuBar^^.wMenus[i].mh, menuRect, startPt, whichItem);
- Delay(flashDelay DIV 4, finalTicks);
- END; { blinking the selected item }
-
- ClipRect(menuFrameRect);
- BackColor(whiteColor);
- ForeColor(blackColor);
- { Blit back original screen image. For a Hierarchical menu }
- { item, the off-screen bitMap/pixMap will include a part of }
- { the inverted parent item. Therefore, we must first blit }
- { back and THEN re-invert !!! }
- CopyBits(MenuDownOSHdl^^.offBitMapPtr^, thePort^.portBits, menuFrameRect, menuFrameRect, srcCopy, NIL);
-
- { Un-hilite the title: }
- IF theMenuBar^^.wMenus[i].menuType = regMenu THEN
- wHiliteMenu(theMenuBar, 0)
- ELSE IF aMac2 THEN
- RedrawParentItem(theMenuBar, i) { i = Hierarchical Menu # }
- ELSE
- BEGIN
- ClipRect(lsTitleRect);
- InvertRect(lsTitleRect);
- END;
-
- IF aMac2 THEN
- CloseCPort(onCScreenPtr)
- ELSE
- ClosePort(onBWScreenPtr);
-
- SetPort(theMenuBar^^.wp);
- { Original menuFrameRect in window coordinates: }
- ValidRect(MenuDownOSHdl^^.drawingRect);
- DisposOffScreen(MenuDownOSHdl);
-
- DisposeRgn(theMenuBar^^.wMenus[i].menuParentRgn);
- DisposeRgn(theMenuBar^^.wMenus[i].cumParentRgn);
- longPtr(TopMenuItemLoc)^ := saveScrollInfo;
- IF theMenuBar^^.wMenus[i].menuType = hierMenu THEN
- Leave;
-
- END { IF i >= 0 }
-
- ELSE { User is not over a Menu. }
- ;
- 100:
- GetMouse(startPt);
- LocalToGlobal(startPt);
-
- END; { WHILE WaitMouseUp }
-
- IF whichItem = 0 THEN
- wMenuSelect := 0
- ELSE
- wMenuSelect := BitShift(whichMenu, 16) + whichItem;
- 200:
- IF aMac2 THEN
- BEGIN
- RGBBackColor(oldBackColor); { "SetColors" is local due to recursion. }
- RGBForeColor(oldForeColor);
- SetMCInfo(origMCTable);
- END; { aMac2 }
- ;
- SetClip(oldClip);
- DisposeRgn(oldClip);
- SetPort(oldPort);
-
- END; { wMenuSelect }
-
-
- FUNCTION wMenuKey (theMenuBar: wMenuBarHandle; ch: char): LONGINT;
-
- VAR
- i, j, whichMenu, whichItem: INTEGER;
- found, enabled: BOOLEAN;
- cmdChar: char;
-
- FUNCTION equalChars (c1, c2: char): BOOLEAN;
- { Filter out difference between UPPER and lower case: }
-
- BEGIN
- IF c1 IN ['a'..'z'] THEN
- c1 := char(ord(c1) + ord('A') - ord('a'));
- IF c2 IN ['a'..'z'] THEN
- c2 := char(ord(c2) + ord('A') - ord('a'));
- equalChars := (c1 = c2);
- END; { equalChars }
-
-
- BEGIN { wMenuKey }
-
- mbHState := HGetState(Handle(theMenuBar));
- MoveHHi(Handle(theMenuBar));
- HLock(Handle(theMenuBar));
-
- found := false;
- i := 0;
-
- WITH theMenuBar^^ DO
- BEGIN
-
- WHILE (NOT found) & (i < numMenus) DO
- BEGIN
-
- WITH wMenus[i] DO
- FOR j := 1 TO CountMItems(mh) DO
- BEGIN
-
- GetItemCmd(mh, j, cmdChar);
- IF equalChars(cmdChar, ch) THEN
- BEGIN
- found := true;
- whichMenu := mh^^.menuID;
- whichItem := j;
- Leave; { FOR loop }
- END; { IF equalChars }
-
- END; { FOR scanning each individual Menu & WITH wMenus[i] }
-
- i := i + 1; { IF found, i = correct # plus 1. }
-
- END; { WHILE scanning each whole Menu }
-
- IF found THEN
- BEGIN
- { The Item is enabled if both it AND its Menu title are enabled: }
- IF j < 32 THEN
- enabled := BitTst(@wMenus[i - 1].mh^^.enableFlags, menuTitleBit - j)
- ELSE
- enabled := true; { Items 32 & beyond. }
- enabled := enabled & BitTst(@wMenus[i - 1].mh^^.enableFlags, menuTitleBit);
- END; { IF found }
-
- END; { WITH theMenuBar^^ }
-
- HSetState(Handle(theMenuBar), mbHState);
-
- IF found & enabled THEN
- BEGIN
- wHiliteMenu(theMenuBar, whichMenu);
- Delay(flashDelay, finalTicks);
- wHiliteMenu(theMenuBar, 0);
- wMenuKey := BitShift(whichMenu, 16) + whichItem;
- END { IF found & enabled }
- ELSE
- wMenuKey := 0;
-
- END; { wMenuKey }
-
-
- PROCEDURE wHiliteMenu (theMenuBar: wMenuBarHandle; menuID: INTEGER);
- { NOTE that this PROC is used only for a regular Menu item. }
- { Apple's MenuDefProc handles a hierarchical Menu item. }
- { For a regular Menu item, we invert the portion of the }
- { titleRect that is both totally visible on the screen and }
- { between the two MSAs. }
-
- CONST
- HiliteMode = $938; { What happened to a simple InvertRect ?!!? }
-
- VAR
- origPort: GrafPtr;
- origClip: RgnHandle;
- i: INTEGER;
- screenBounds, betweenMSAs, visAllTitles, visThisTitle, visString: Rect;
- lmbHState: SignedByte; { Gotta be local to avoid interference }
- { with the global = mbHState. }
- oldMCTable: MCTableHandle; { Color stuff ... }
- oldForeColor, oldBackColor, hiliteForeColor, hiliteBackColor: RGBColor;
- oldTxSize, oldTxFont, oldTxMode: INTEGER;
- oldTxStyle: Style;
-
-
- BEGIN
-
- { Needed because wHiliteMenu is called with pressing }
- { a CMD-key whereupon a window may not be around. }
- IF FrontWindow = NIL THEN
- EXIT(wHiliteMenu);
-
- lmbHState := HGetState(Handle(theMenuBar));
- IF NOT BitTst(@lmbHState, 0) THEN
- BEGIN
- MoveHHi(Handle(theMenuBar));
- HLock(Handle(theMenuBar));
- END; { NOT already locked !! }
-
- WITH theMenuBar^^ DO
- BEGIN
- GetPort(origPort);
- SetPort(wp);
- origClip := NewRgn;
- GetClip(origClip);
- ;
- oldTxSize := thePort^.txSize; { Just as with wMenuSelect PROC }
- oldTxFont := thePort^.txFont; { because wMenuKey calls us. }
- oldTxStyle := thePort^.txFace;
- oldTxMode := thePort^.txMode;
- TextFont(systemFont);
- myTextSize(sizeFont);
- TextFace([]);
- TextMode(srcOr);
- ;
- IF aMac2 THEN
- BEGIN
- GetForeColor(oldForeColor);
- GetBackColor(oldBackColor);
- oldMCTable := GetMCInfo;
- SetMCInfo(theMenuBar^^.wMCTable);
- END;
-
- screenBounds := gScreen;
- GlobalLocal(screenBounds);
- betweenMSAs := WBMrect;
- InsetRect(betweenMSAs, leftMSArect.right, 0); { ... or rightMSArect.left }
- IF SectRect(screenBounds, betweenMSAs, visAllTitles) THEN
- BEGIN
-
- { Un-highlight previously highlighted Menu title by re-inverting }
- { it or re-drawing it if on a machine with Color QuickDraw. }
- { This is similiar to the gyrations within Apple's MenuDefProc. }
- { The latter does NOT call _InverRect for a color Mac, but rather }
- { _EraseRect followed by a redraw of the Menu item. }
- IF titleHilited <> noneHilited THEN
- BEGIN
- WITH wMenus[titleHilited], titleRect DO
- BEGIN
- IF SectRect(visAllTitles, titleRect, visThisTitle) THEN
- BEGIN { ALWAYS true if hilited. }
- ClipRect(visThisTitle);
- IF aMac2 THEN { See wDrawMenuBar PROC. }
- BEGIN
- wSetColorMenu(mceMenuBar, mceMenuBar);
- EraseRect(visThisTitle);
- MoveTo(left + invertOverlap, bottom - (mBarHt - menuFrame - sizeFont) DIV 2);
- wSetColorMenu(mh^^.menuID, mceMenuTitle);
- DrawString(mh^^.menuData);
- END
- ELSE
- InvertRect(visThisTitle);
- ValidRect(visThisTitle);
- END; { IF SectRect: visThisTitle NOT empty }
- END; { WITH }
- ;
- titleHilited := noneHilited; { So we don't re-invert. }
- END; { IF hilited }
-
- IF menuID <> 0 THEN
- BEGIN
- i := 0;
- WHILE (i < numMenus) & (wMenus[i].mh^^.menuID <> menuID) DO
- i := i + 1;
-
- IF i <> numMenus THEN
- WITH wMenus[i] DO
- BEGIN
- IF SectRect(visAllTitles, titleRect, visThisTitle) THEN
- BEGIN
- visString := visThisTitle;
- WITH visString DO
- BEGIN
- IF (leftMSArect.right > right - invertOverlap - 2 * menuFrame) | (screenBounds.left > right - invertOverlap - 2 * menuFrame) THEN
- right := right - invertOverlap - 2 * menuFrame;
- ;
- IF (rightMSArect.left < left + invertOverlap + 2 * menuFrame) | (screenBounds.right < left + invertOverlap + 2 * menuFrame) THEN
- left := left + invertOverlap + 2 * menuFrame;
- END; { WITH visString }
-
- IF NOT EmptyRect(visString) THEN
- BEGIN
- ClipRect(visThisTitle);
- IF aMac2 THEN
- BEGIN
- { Text's color becomes the background color and the }
- { MenuBar's background color becomes the foreground. }
- wSetColorMenu(menuID, mceMenuTitle);
- GetForeColor(hiliteBackColor);
- HiliteColor(hiliteBackColor);
- wSetColorMenu(mceMenuBar, mceMenuBar);
- { GetBackColor(hiliteForeColor); }
- { RGBBackColor(hiliteForeColor); }
- BitClr(Ptr(HiliteMode), pHiliteBit);
- END; { on a color machine }
- InvertRect(visThisTitle);
- ValidRect(visThisTitle);
- ;
- titleHilited := i;
- END; { visString NOT empty }
- END; { IF SectRect: visThisTitle NOT empty }
- END; { IF i <> numMenus & WITH }
- END { IF menuID <> 0 }
- ELSE { as in HiliteMenu(0). }
- ; { Taken care of by IF titleHilited <> noneHilited }
-
- END; { IF SectRect: visAllTitles NOT empty }
-
- IF aMac2 THEN
- BEGIN
- SetMCInfo(oldMCTable);
- RGBForeColor(oldForeColor);
- RGBBackColor(oldBackColor);
- END;
- ;
- TextFont(oldTxFont);
- myTextSize(oldTxSize);
- TextFace(oldTxStyle);
- TextMode(oldTxMode);
- ;
- SetClip(origClip);
- DisposeRgn(origClip);
- SetPort(origPort);
- END; { WITH theMenuBar^^ }
-
- HSetState(Handle(theMenuBar), lmbHState);
-
- END; { wHiliteMenu }
-
-
- PROCEDURE wChangeMenuBarSize (wp: WindowPtr; zooming: BOOLEAN);
- { Called in response to zooming & growing the window. }
- { Note: NOT zooming = growing. }
-
-
- BEGIN
-
- mBar := wGetMenuBar(wp);
- ;
- IF mBar <> NIL THEN
- BEGIN { Only a part of wClearMenuBar ... }
- GetWBMrects(wp, WBMrect, leftMSArect, rightMSArect);
-
- wHiliteMenu(mBar, 0);
-
- IF NOT zooming THEN { doZoom calls InvalRect(wp^.portRect) }
- InvalRect(rightMSArect);
-
- IF mBar^^.rightScrollPoly <> NIL THEN
- BEGIN
- KillPoly(mBar^^.rightScrollPoly);
- mBar^^.rightScrollPoly := NIL; { Mark as gone !! }
- END;
-
- IF zooming & (mBar^^.leftScrollPoly <> NIL) THEN
- BEGIN
- KillPoly(mBar^^.leftScrollPoly);
- mBar^^.leftScrollPoly := NIL;
- END;
- END; { window has a WBM }
-
- END; { wChangeMenuBarSize }
-
-
-
- END. { UNIT = wBarMenuProc }